﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Entidades
{
    public class ConfiguracaoFactory
    {

        private static List<ConfiguracaoFinal> solucao = new List<ConfiguracaoFinal>();

        public static List<ConfiguracaoFinal> Solucao
        {
            get { return ConfiguracaoFactory.solucao; }
            set { ConfiguracaoFactory.solucao = value; }
        }
     

        public ConfiguracaoFactory()
        {
        }
        

        private void configurar(LinkedList<ListaConfiguracoes> lCfg, double[] valores)
        {
            lCfg.AddLast(new ListaConfiguracoes());

            for (int i = 0; i < valores.Length; i++)
            {
                ConfiguracaoAux cf = new ConfiguracaoAux();
                cf.Valor = valores[i];
                lCfg.Last.Value.Configuraçoes.Add(cf);

            }
        }

        public void inicializar(LinkedList<ListaConfiguracoes> lCfg)
        {
            if (lCfg.Count != 0)
                lCfg = new LinkedList<ListaConfiguracoes>();

            if (solucao.Count != 0)
                solucao = new List<ConfiguracaoFinal>();

            //As configurações do experimento 1 foram validadas no dia 15/03 ao serem executadas no computador do trabalho. Elas geraram o mesmo resultado do dia 18/12.
            //O experimento não chegou a terminar pois eu o interrompi para realizar a mesma validação no experimento 2. Mas já verifiquei que pelo menos 5 instancias possuem
            // o mesmo resultado em ambas execuções. Estes resultados estão em C:\Users\Geraldo Megale\SkyDrive\Mestrado\Tese\Experimentos\Experimentos_Dissertacao\Experimento_1_18_12_2014_0001\Validação_Experimento_1
          //  -----------------------------------------------------------------------------------------------------------------
            ////e1c1 a e1c12
            //Double[] vicio = {0.6,0.7,0.8}; //foi utilizado na execucao enviada para a professora dia 18/12/2014 (combinado)
            //Double[] vizinhos = {0};
            //Double[] reset = {1};
            //Double[] combinado = { 0, 1, 2, 3 };
            //Double[] decodificador = { 0 };




            //e1c13
            //Double[] vicio = {0.7}; //foi utilizado na execucao enviada para a professora dia 16/12/2014 (fixo)
            //Double[] vizinhos = {0};
            //Double[] reset = {0};
            //Double[] elite = {0.2};
            //Double[] mutantes = {0.15};

            //  ------------------------------------------------------------------------------------------------------------





            ////e2c4 e2c9 e2c14 e2c19 e2c24
            ////foi utilizado na execucao enviada para a professora dia XXXXXX do experimento 2 somente com o bf/lbf
            //Double[] vizinhos = { 0, 0.2, 0.5, 0.7, 1 };
            //Double[] decodificador = { 4 };
            ////melhor configuração do experimento anterior.
            //Double[] vicio = { 0.6 };
            //Double[] combinado = { 1 }; //e1c2
//           --------------------------------------------------------------------------------



            ////e2c1 a e2c25 - (e2c5 e2c10 e2c15 e2c20)
            //foi utilizado na execucao enviada para a professora dia XXXXXX do experimento 2 somente com o bf, lbf , ff , wf

            //Double[] vizinhos = {0 , 0.2 , 0.5 , 0.7 , 1 }; 
            //Double[] decodificador = {0, 1 , 2 , 3};

            //////melhor configuração do experimento anterior.
            //Double[] vicio = { 0.6 };
            //Double[] combinado = {1}; //e1c2


            //e3c1 - experimento 3
            //experimento 3 - utilizando o e2c24 em 3 novas instâncias. 
            Double[] vizinhos = { 0 };
            Double[] decodificador = { 4 }; //best fit com o least best fit;

            //melhor configuração do experimento anterior.
            Double[] vicio = { 0.6 };
            Double[] combinado = { 1 }; //e1c2



            //e3c2 - experimento 3
            //experimento 3 - utilizando o e2c20 em 3 novas instâncias. 
            //Double[] vizinhos = { 1 };
            //Double[] decodificador = { 0 }; //best fit;

            //melhor configuração do experimento anterior.
            //Double[] vicio = { 0.6 };
            //Double[] combinado = { 1 }; //e1c2



            ////experimento relacionado aos critérios de parada.
            ////experimento 3 - utilizando o e2c24 nas 12 instancias com 2000 execuções. 
            //Double[] vizinhos = { 0 };
            //Double[] decodificador = { 4 }; //best fit com o least best fit;

            ////melhor configuração do experimento anterior.
            //Double[] vicio = { 0.6 };
            //Double[] combinado = { 1 }; //e1c2



            configurar(lCfg, vicio);
            configurar(lCfg, vizinhos);
            configurar(lCfg, combinado);
            configurar(lCfg, decodificador);



         
        }

     
        public void GenerateAllConfigs(LinkedListNode<ListaConfiguracoes> listaCfgs, List<Double> cfgAux)
        {
            if (listaCfgs == null)
            {
                ConfiguracaoFinal cf = new ConfiguracaoFinal();
                cf.Valores = new double[cfgAux.Count];


                for (int i = 0; i < cf.Valores.Count(); i++)
                {
                    cf.Valores[i] = cfgAux[i];
                }

                solucao.Add(cf);

                int pos = solucao.Count;
                solucao[--pos].ToString();

                return;
            }


            for (int i = 0; i < listaCfgs.Value.Configuraçoes.Count; i++)
            {
                cfgAux.Add(listaCfgs.Value.Configuraçoes[i].Valor);

                GenerateAllConfigs(listaCfgs.Next, cfgAux);

                int tam = cfgAux.Count;
                tam--;

                cfgAux.RemoveAt(tam);

            }
        }

        public void ConvertToRealConfigsCombinado(List<Configuration2> cfgs)
        {
            int id = 0;
            foreach (ConfiguracaoFinal cf in ConfiguracaoFactory.solucao)
            {
                Configuration2 c = new Configuration2();

                c.AvaliarReconfigPopulacao = true;
                c.ParadaFixa = false;
                c.ParadaDinamica = true;

                c.AvaliarResetPopulacao = false;
                c.MaxClusters = 0.4;
                c.MinClusters = 0.2;
                c.QtdeGeracoes = 1000;



                c.PopulationInheritanceProbability = cf.Valores[0];
                c.Porc_Vizinhos = cf.Valores[1];
                c.Combinado = (int) cf.Valores[2];

                if (cf.Valores[2] == 0)
                {
                    c.EliteProb = 0.1;
                    c.MutantProb = 0.3;
                }

                else if (cf.Valores[2] == 1)
                {
                    c.EliteProb = 0.25;
                    c.MutantProb = 0.05;
                }

                else if (cf.Valores[2] == 2)
                {
                    c.EliteProb = 0.1;
                    c.MutantProb = 0.05;
                }

                else if (cf.Valores[2] == 3)
                {
                    c.EliteProb = 0.25;
                    c.MutantProb = 0.3;
                }

                if (cf.Valores[3] == 0)
                {
                    c.EstrategiaDecodificacao = "Algoritmos.clustersPorVizinho.NosHandler_BestFit";
                }

                else if (cf.Valores[3] == 1)
                {
                    c.EstrategiaDecodificacao = "Algoritmos.clustersPorVizinho.NosHandler_FirstFit";
                }

                else if (cf.Valores[3] == 2)
                {
                    c.EstrategiaDecodificacao = "Algoritmos.clustersPorVizinho.NosHandler_LeastBestFit";
                }

                else if (cf.Valores[3] == 3)
                {
                    c.EstrategiaDecodificacao = "Algoritmos.clustersPorVizinho.NosHandler_WorstFit";
                }

                c.Id = id;
                id++;

                cfgs.Add(c);

            }
        }


        public void ConvertToRealConfigs(List<Configuration2> cfgs)
        {
            int id = 0;
            foreach (ConfiguracaoFinal cf in ConfiguracaoFactory.solucao)
            {
                Configuration2 c = new Configuration2();

                c.AvaliarReconfigPopulacao = false;

                if (cf.Valores[4] == 0)
                    c.AvaliarResetPopulacao = false;
                else
                    c.AvaliarResetPopulacao = true;

                c.EliteProb = cf.Valores[0];
                c.MaxClusters = 0.4;
                c.MinClusters = 0.2;
                c.MutantProb = cf.Valores[1];
                c.Population = 100;
                c.PopulationElite = c.EliteProb * c.Population;
                c.PopulationMutant = c.MutantProb * c.Population;
                c.PopulationInheritanceProbability = cf.Valores[2];
                c.Porc_Vizinhos = cf.Valores[3];
                c.QtdeGeracoes = 1000;
                c.Id = id;
                id++;

                cfgs.Add(c);

            }
        }
    }
}
